package com.example.teesystem.common.exception;

import cn.hutool.core.exceptions.ValidateException;
import com.example.teesystem.common.utils.Response;
import com.example.teesystem.common.utils.ResultCode;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Set;

/**
 * 自定义异常处理器
 */
@RestControllerAdvice
public class CustomExceptionHandler {
    /**
     * 处理自定义异常
     * @param e 自定义的异常类型
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public Response handleCustomException(CustomException e) {
        System.out.println("CustomException:");
        System.out.println(e.getMessage());
        return Response.error(e.getMsg(), e.getCode()).put("data", e.getMessage());
    }
    
    /**
     * 处理 Validator 校验失败异常
     * @param e
     * @return
     */
    @ExceptionHandler(ValidateException.class)
    public Response handleValidateException(ValidateException e) {
        System.out.println("ValidateException:");
        System.out.println(e.getMessage());
        return Response.error(e.getMessage(), ResultCode.PARAMETER_MISS.getCode());
    }
    
    /**
     * 处理参数转化失败异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Response handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        System.out.println(e.getMessage());
        return Response.error(ResultCode.PARAM_CONVERT_FAIL.getMsg(), ResultCode.PARAM_CONVERT_FAIL.getCode());
    }
    
    /**
     * 处理 @Valid 参数校验失败异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response handleValidException(MethodArgumentNotValidException e) {
        HashMap<String, String> map = new HashMap<>();
        BindingResult result = e.getBindingResult();
        result.getFieldErrors()
                .forEach(fieldError -> map.put(fieldError.getField(), fieldError.getDefaultMessage()));
        return Response.error(ResultCode.VALID_EXCEPTION.getMsg(), ResultCode.VALID_EXCEPTION.getCode())
                .put("data", map);
    }
    
    /**
     * 处理 @Validated 参数校验失败异常
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Response handleValidException(ConstraintViolationException e) {
        HashMap<String, String> map = new HashMap<>();
        Set<ConstraintViolation<?>> result = e.getConstraintViolations();
        result.forEach(exp -> map.put(exp.getPropertyPath().toString(), exp.getMessageTemplate()));
        
        return Response.error(ResultCode.VALID_EXCEPTION.getMsg(), ResultCode.VALID_EXCEPTION.getCode())
                .put("data", map);
    }
    
    /**
     * 抛出其它异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Response handleException(Exception e){
        System.out.println("handleException:");
        System.out.println(e.getMessage());
        System.out.println(e.getClass());
        return Response.error(ResultCode.UNKNOWN_EXCEPTION.getMsg(), ResultCode.UNKNOWN_EXCEPTION.getCode())
                .put("data", e.getMessage());
    }
}
